import 'dart:convert';
import 'dart:math';

import 'package:get/get.dart';
import 'package:kkhousekeep/config/constant.dart';
import 'package:kkhousekeep/models/home_banner_entity.dart';
import 'package:kkhousekeep/models/home_notice_entity.dart';
import 'package:kkhousekeep/models/home_village_entity.dart';
import 'package:kkhousekeep/net/home_connect.dart';
import 'package:kkhousekeep/page/home/convenient/notice/notice_page.dart';
import 'package:kkhousekeep/page/home/convenient/order/work_order_page.dart';
import 'package:logger_util/logger_util.dart';
import 'package:shared_preferences/shared_preferences.dart';

import '../../models/home_community_entity.dart';
import '../../models/home_exist_new_mag_entity.dart';
import '../../models/home_room_entity.dart';
import '../../models/notice_list_entity.dart';
import '../../tools/shared_preferences.dart';
import '../login/login_controller.dart';
import 'community_info_page.dart';
import 'convenient/bill/bill_page.dart';
import 'convenient/notice/notice_detail_page.dart';
import 'convenient/repair/repair_home_page.dart';
import 'convenient/visitor/record_list.dart';
import 'switch_houses_page.dart';

class HomeController extends GetxController {
  final UserType userType;

  HomeController({
    this.userType = UserType.tenant,
  });

  var roomInfo = HomeRoomObjList().copyWith(
    roomId: -1,
    cityName: '',
    communityName: '',
    buildingName: '',
    unitName: '',
    roomName: '',
  );

  var villageInfo = HomeVillageObj().copyWith(id: -1, name: '');

  var address = ''.obs;

  var banners = <HomeBannerObjList>[].obs;
  var bannerIndex = 0.obs;

  var serviceList = <ServiceType>[];
  var existNewMsg = HomeExistNewMagObj()
      .copyWith(noticeExist: false, workOrderExist: false, billExist: false)
      .obs;

  var noticeModels = <HomeNoticeObjList>[].obs;
  var homeNoticeModels = <List<HomeNoticeObjList>>[].obs;

  var tabsModels = TabType.values;
  var enableTabType = TabType.all.obs;
  var communityMap = <TabType, List<HomeCommunityObjList>>{}.obs;

  late HomeConnect homeConnect;

  @override
  void onInit() {
    homeConnect = Get.put(HomeConnect());
    _initData();
    loadNetworkData();
    super.onInit();
  }

  void performClickTab(TabType type) {
    if (enableTabType.value == type || userType == UserType.property) {
      return;
    }
    enableTabType.value = type;
    var dataList = communityMap[type];
    if (dataList?.isEmpty ?? true) {
      homeConnect
          .getCommunityList(type.id)
          .then((value) => communityMap[type] = value);
    }
  }

  void performClickAddress() async {
    var id = userType == UserType.property ? villageInfo.id : roomInfo.roomId;
    var arguments = {
      ArgumentKey.id: id,
      ArgumentKey.userType: userType,
    };
    var result =
        await Get.to(() => const SwitchHousesPage(), arguments: arguments);
    saveRoomOrVillageInfo(result);
    loadNetworkData();
  }

  Future performClickConvenientServiceItem(ServiceType type) async {
    if (type == ServiceType.bill) {
      await Get.to(() => const BillPage());
      loadNetworkData();
      return;
    }

    if (type == ServiceType.repair) {
      await Get.to(() => const RepairHomePage());
      loadNetworkData();
      return;
    }

    if (type == ServiceType.visitor) {
      await Get.to(() => const BuildVisitorRecordPage());
      loadNetworkData();
      return;
    }

    if (type == ServiceType.notice) {
      await Get.to(() => const NoticePage());
      loadNetworkData();
      return;
    }

    if (type == ServiceType.order) {
      await Get.to(() => const WorkOrderPage());
      loadNetworkData();
      return;
    }
  }

  Future performClickCommunityItem(HomeCommunityObjList entity) async {
    var arguments = {
      ArgumentKey.id: entity.id,
      ArgumentKey.serviceType: entity.serviceType,
    };
    await Get.to(() => const CommunityInfoPage(), arguments: arguments);
    loadNetworkData();
  }

  void _initData() {
    serviceList.clear();
    if (userType != UserType.property) {
      serviceList.addAll([
        ServiceType.bill,
        ServiceType.repair,
        ServiceType.visitor,
        ServiceType.notice,
      ]);
      return;
    }
    if (userType == UserType.property) {
      serviceList.addAll([
        ServiceType.order,
        ServiceType.notice,
      ]);
    }
  }

  Future<void> loadNetworkData({bool isLoadAllNotice = false}) async {
    if (userType == UserType.property) {
      await homeConnect.getPropertyVillagesInfo().then(
        (value) async {
          if (value.id == -2) {
            var sp = await SharedPreferences.getInstance();
            if (sp.containsKey(SpKey.villageInfo)) {
              HomeVillageObj village = HomeVillageObj.fromJson(
                  jsonDecode(sp.getString(SpKey.villageInfo) ?? ''));
              await homeConnect.switchPropertyVillage(id: village.id).then(
                    (value) => saveRoomOrVillageInfo(
                      {
                        ArgumentKey.token: value,
                        ArgumentKey.data: village,
                      },
                    ),
                  );
              return;
            }
          }
          villageInfo = value;
          address.value = villageInfo.name;
        },
      );
    }
    homeConnect.getBannerList().then((banner) {
      banners.value = banner;
    });
    homeConnect.getServiceNewMsg().then((value) => existNewMsg.value = value);
    homeConnect
        .getNoticeList(userType: userType)
        .then((value) => handleNoticeList(value, isLoadAllNotice));
    if (userType != UserType.property) {
      homeConnect.getRoomInfo().then((value) {
        roomInfo = value;
        address.value = '${roomInfo.communityName}${roomInfo.buildingName}'
            '${roomInfo.unitName}${roomInfo.roomName}';
      });
      homeConnect
          .getCommunityList(enableTabType.value.id)
          .then((value) => communityMap[enableTabType.value] = value);
    }
    return Future.value();
  }

  void performClickNoticeItem(HomeNoticeObjList model) async {
    if (model.id == -1) {
      return;
    }
    var arguments = NoticeListObjList().copyWith(
      id: model.id,
      title: model.title,
      publisher: model.publisher,
      read: model.read,
      cid: model.cid,
      updateTime: model.updateTime,
      createTime: model.createTime,
      publishTime: model.publishTime,
      views: model.views,
      context: model.context,
    );
    await Get.to(() => const NoticeDetailPage(), arguments: arguments);
    loadNetworkData();
  }

  Future saveRoomOrVillageInfo(dynamic result) async {
    if (result is! Map) {
      logE('result类型异常,请检查!');
      return Future.value();
    }

    String key = '';
    String token = result[ArgumentKey.token] ?? '';
    var data = result[ArgumentKey.data] ?? '';

    if (token.isEmpty || data is String) {
      logE('返回数据异常,请检查!');
      return Future.value();
    }

    if (data is HomeRoomObjList) {
      key = SpKey.roomInfo;
      roomInfo = data;
      address.value = '${roomInfo.communityName}${roomInfo.buildingName}'
          '${roomInfo.unitName}${roomInfo.roomName}';
    }

    if (data is HomeVillageObj) {
      key = SpKey.villageInfo;
      villageInfo = data;
      address.value = villageInfo.name;
    }
    if (key.isNotEmpty) {
      var sp = await SharedPreferences.getInstance();
      sp.setString(key, jsonEncode(data.toJson()));
      sp.setString(SpKey.accessToken, token);
    }
  }

  void handleNoticeList(List<HomeNoticeObjList> value, bool isLoadAllNotice) {
    homeNoticeModels.clear();
    List<HomeNoticeObjList> defaultNotice = [
      HomeNoticeObjList().copyWith(
          id: -1,
          title: '目前暂无通知',
          publisher: '',
          context: '',
          views: 0,
          publishTime: '',
          createTime: '',
          updateTime: '',
          cid: -1,
          read: 0),
    ];
    if (value.isEmpty) {
      noticeModels.value = defaultNotice;
      homeNoticeModels.add(noticeModels);
      return;
    }
    if (isLoadAllNotice) {
      noticeModels.value = value;
      return;
    }
    List<HomeNoticeObjList> noneReadNoticeList = [];
    for (var homeNoticeObj in value) {
      if (homeNoticeObj.read == 0) {
        noneReadNoticeList.add(homeNoticeObj);
      }
    }
    var count = min(3, noneReadNoticeList.length);
    if (count == 0) {
      homeNoticeModels.add(defaultNotice.toList());
      return;
    }
    var groundOfNoneReadNotice = <HomeNoticeObjList>[];
    for (var i = 0; i < noneReadNoticeList.length; i++) {
      if (noneReadNoticeList.length <= 3) {
        groundOfNoneReadNotice.add(noneReadNoticeList[i]);
        if (i == noneReadNoticeList.length - 1) {
          homeNoticeModels.add(groundOfNoneReadNotice);
        }
      } else {
        if (groundOfNoneReadNotice.length < 3) {
          groundOfNoneReadNotice.add(noneReadNoticeList[i]);
          if (i == noneReadNoticeList.length - 1) {
            homeNoticeModels.add(groundOfNoneReadNotice);
          }
        } else {
          List<HomeNoticeObjList> tempList = [];
          for (var element in groundOfNoneReadNotice) {
            tempList.add(element);
          }
          homeNoticeModels.add(tempList);
          groundOfNoneReadNotice.clear();
          groundOfNoneReadNotice.add(noneReadNoticeList[i]);
          if (i == noneReadNoticeList.length - 1) {
            homeNoticeModels.add(groundOfNoneReadNotice);
          }
        }
      }
    }
    noticeModels.value = noneReadNoticeList.sublist(0, count);
  }
}

enum ServiceType {
  bill(id: 0, name: '物业账单', iconName: 'hone_service_property_bills.png'),
  repair(id: 1, name: '物业报修', iconName: 'home_service_property_repair.png'),
  visitor(id: 2, name: '来访登记', iconName: 'hone_service_visitor.png'),
  order(id: 3, name: '报修工单', iconName: 'home_service_property_repair.png'),
  notice(id: 4, name: '通知公告', iconName: 'hone_service_notification.png');

  final int id;
  final String name;
  final String iconName;

  const ServiceType({
    required this.id,
    required this.name,
    required this.iconName,
  });
}

enum TabType {
  all(id: 0, tabName: '全部'),
  houseLease(id: 1, tabName: '房屋租贷'),
  housekeeping(id: 2, tabName: '家政服务'),
  airTicket(id: 3, tabName: '机票代售'),
  motorVehicleInspection(id: 4, tabName: '机动车代理');

  final int id;
  final String tabName;

  const TabType({
    required this.id,
    required this.tabName,
  });

  static TabType getTabTypeById(int id) {
    return TabType.values.firstWhereOrNull((element) => element.id == id) ??
        TabType.all;
  }
}
